#pragma once
#include <stdio.h>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
using namespace std;

template <class T>
class Vector
{
public:
    Vector():_start(NULL),_finish(NULL),_endOfstorage(NULL)
    {}
    ~Vector()
    {
        delete []_start;
        _start=_finish=_endOfstorage=NULL;
    }
    size_t Size() const
    {
        return _finish-_start;
    }
    size_t Capacity() const
    {
        return _endOfstorage-_start;
    }
    
    Vector(const Vector<T> &v);
    Vector<T> operator=(const Vector<T> &v);
    void PushBack(const T & value);
    void PushFront(const T & value);
    void PopFront();
    T & Back();
    T & Front();
    bool Empty();
    void PopBack();
    void Insert(size_t pos,const T & value);
    void Erase(size_t pos);
    void clear();
    void Display();

protected:
    T *_start;
    T *_finish;
    T *_endOfstorage;
    void Expend(size_t n)//扩容可以不作为接口
    {
        if(Capacity()==0)
        {//最开始
            n=3;
        }
        if(n>Capacity())
        {
            size_t size=Size();//这里需要先将size保存下来
            T * tmp=new T[n];
            T * start=tmp;
            T *finish=_start;
            while(finish!=_finish)
            {
                *start=*finish;
                ++start;
                ++finish;
            }//将旧的数据先复制过去
            clear();//清理掉旧的
            _start=tmp;
            _finish=tmp+size;
            _endOfstorage=_start+n;
        }
    }
};
template <class T>
Vector<T>::Vector(const  Vector<T> &v):_start(NULL),_finish(NULL),_endOfstorage(NULL)
{
   _start=new T[v.Size()];
    T *start=_start;
    T *finish=v._start;
    while(finish!=v._finish)
    {
        *start=*finish;
        ++start;
        ++finish;
    }
    //将v中的数据都拷贝进去
    _finish=_start+v.Size();
    _endOfstorage=_finish;
}
template<class T>
Vector<T> Vector<T>:: operator=(const Vector<T> &v)
{
    //if(this!=&v)
    //{

    //T *tmp=new T[v.Size()];
    //T *start=tmp;
    //T *finish=v._start;
    //while(finish!=v._finish)
    //{
    //    *start=*finish;
    //    start++;
    //    finish++;
    //}
    //clear();
    //_start=tmp;
    //_finish=_start+v.Size();
    //_endOfstorage=_finish;
    //}
    //采用现代写法，函数结束后会自己调用析构函数
    //采用传统写法
    if(this!=&v)
    {
        Vector<T> tmp(v);
        swap(tmp._start,_start);
        swap(tmp._finish,_finish);
        swap(tmp._endOfstorage,_endOfstorage);
    }
    return *this;
}
template<class T>
void Vector<T>::Insert(size_t pos,const T & value)
{
    if(pos>Size())
    {//Size()位置也是可以进行插入的,为了进行尾插
        return;
    }
    if(Size()>=Capacity())
    {//需要进行扩容
        Expend(Capacity()*2);
    }
    //然后将pos位置后面的数据向后移动
    T *cur=_finish;//这里采用指针的方法是为了避免pos的size_t类型的比较
    while(cur!=_start+pos)
    {
        *cur=*(cur-1);
        --cur;
    }
    _start[pos]=value;
    _finish++;//完成一次插入后需要将_finish后移
}
template<class T>
void Vector<T>:: PushBack(const T & value)
{//这里传参要传引用，因为value若是一个链表或者比较大的数据，传值会进行拷贝构造，代价比较大

    Insert(Size(),value);
}
template<class T>
void Vector<T>::PopBack()
{
    Erase(Size()-1);
}
template<class T>
void Vector<T>::Erase(size_t pos)
{
    if(pos>=Size())
    {
        return;
    }
    if(Size()==0)
    {
        return;
    }
    //将pos位置开始的元素向前移动
    T *cur=_start+pos+1;
    while(cur!=_finish)
    {
        *(cur-1)=*(cur);
        cur++;
    }
    --_finish;//删除一个元素之后需要将_finish向前移动
}

template<class T>
void Vector<T>::PushFront(const T & value)
{
    Insert(0,value);
}

template<class T>
void Vector<T>::PopFront()
{
    Erase(0);
}

template<class T>
T & Vector<T>::Back()//这里没有做是否为空的判断，是因为这个接口是为了给后面的适配器用的
{
    return _start[Size()-1];
}

template<class T>
T & Vector<T>::Front()
{
    return _start[0];
}

template<class T>
bool Vector<T>::Empty()
{
    return _finish==_start;
}

template<class T>
void Vector<T>::clear()
{
    delete[] _start;
    _start=_finish=_endOfstorage=NULL;
}
template<class T>
void Vector<T>::Display()
{
    if(Size()==0)
    {
        return;
    }
    T *cur=_start;
    while(cur!=_finish)
    {
        cout<<*cur<<" ";
        ++cur;
    }
    cout<<endl;
}
